package cn.hzc.fortess.system.service;

import cn.hzc.fortess.core.common.annotion.CURDLog;
import cn.hzc.fortess.core.common.annotion.CURDType;
import cn.hzc.fortess.core.common.constant.Const;
import cn.hzc.fortess.core.common.BizErrorEnum;
import cn.hzc.fortess.core.common.exception.ServiceException;
import cn.hzc.fortess.core.shiro.ShiroKit;
import cn.hzc.fortess.core.shiro.ShiroUser;
import cn.hzc.fortess.system.dao.ProjectDao;
import cn.hzc.fortess.system.entity.Project;
import cn.hzc.fortess.system.entity.Role;
import cn.hzc.fortess.system.page.Pagination;
import cn.hzc.fortess.system.search.ProjectSearch;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class ProjectServiceImpl implements ProjectService {

    @Autowired
    ProjectDao projectDao;
    @Autowired
    MenuService menuService;
    @Autowired
    RoleService roleService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CURDLog(value = "新增项目")
    public void add(Project entity) {
        if (projectDao.findExist(entity.getProjectCode(), entity.getProjectName()) != null) {
            throw new ServiceException(BizErrorEnum.PROJECT_EXIST);
        }
        entity.setCreateTime(new Date());
        entity.setCreateUser(ShiroKit.getUser().getAccount());
        projectDao.insert(entity);
        //初始化项目菜单
        menuService.createRootMenu4Project(entity);
        //建立项目管理员
        roleService.createAdminRole4Project(entity);
    }

    @Override
    @CURDLog(value = "更新项目", curdType = CURDType.EDIT)
    public void update(Project entity) {
        entity.setUpdateTime(new Date());
        entity.setUpdateUser(ShiroKit.getUser().getAccount());
        projectDao.update(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CURDLog(value = "删除项目", curdType = CURDType.DELETE)
    public void delete(Integer id) {
        projectDao.delete(id);
        projectDao.deleteRelationByProject(id);
        menuService.deleteByProject(id);
        roleService.deleteByProject(id);
    }


    @Override
    public Project getById(Integer id) {
        return projectDao.getById(id);
    }

    @Override
    public List<Project> getUserProject() {
        if (ShiroKit.getUser().isAdministrator()) {
            return projectDao.findAll(null);
        }
        return getUserProjectList(ShiroKit.getUser().getId()).stream()
                .filter(project -> (!Objects.equals(Const.SAM_PROJECT_ID, project.getId()))).collect(Collectors.toList());
    }

    @Override
    public List<Project> getProjectByUserRole(ShiroUser shiroUser) {
        if (CollectionUtils.isEmpty(shiroUser.getRoleList())) {
            return Lists.newArrayList();
        }
        return projectDao.findProjectByUserRole(shiroUser.getRoleList().parallelStream().map(Role::getId).collect(Collectors.toList()));
    }


    private List<Project> getUserProjectList(Integer userId) {
        final List<Integer> managerProjectList = projectDao.findMyProjectIds(userId);
        if (CollectionUtils.isEmpty(managerProjectList)) {
            return Lists.newArrayList();
        }
        return projectDao.findAll(managerProjectList);
    }


    @Override
    public List<Integer> getUserProjectIds() {
        return this.getUserProject().parallelStream()
                .map(Project::getId).collect(Collectors.toList());
    }

    @Override
    public List<Project> getAllByLesseeId(Integer lesseeId) {
        return projectDao.findByLesseeId(lesseeId);
    }

    @Override
    public Pagination getPage(ProjectSearch search) {
        if (!ShiroKit.getUser().isAdministrator()) {
            search.setProjectIds(getUserProjectIds());
        }
        Pagination pagination = new Pagination();
        pagination.setCount(projectDao.count(search));
        if (pagination.getCount() > 0) {
            List<Project> list = projectDao.page(search);
            list.stream().forEach(project -> {
                List<Role> roles = roleService.getByProjectId(project.getId());
                project.setRoles(CollectionUtils.isEmpty(roles) ? Lists.newArrayList() :
                        roles.stream().map(Role::getRoleName).collect(Collectors.toList()));
            });
            pagination.setData(list);
        }
        return pagination;
    }
}
